package com.xiu.json;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * @Author: tjc
 * @description
 * @Date Created in 19:00 2023-08-28
 */
public class ObjectMapper {

    public static <T> T readValue(String json, Class<T> valueTarget) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        T bean = valueTarget.getDeclaredConstructor().newInstance();
        Map<String, Method> methodNames = Arrays.stream(valueTarget.getDeclaredMethods())
                .collect(Collectors.toMap(method -> method.getName().toLowerCase(), method -> method));
        JSONObject jsonObject = JSON.parseObject(json);

        for (Map.Entry<String, Object> kv : jsonObject.kvSet()) {
            String keyName = "set" + kv.getKey();
            if (methodNames.containsKey(keyName)) {
                Method m = methodNames.get(keyName);
                m.invoke(bean, kv.getValue());
            }
        }
        return bean;
    }

    public static <T> String writeValue(T value) throws InvocationTargetException, IllegalAccessException {
        Method[] methods = value.getClass().getDeclaredMethods();
        StringJoiner joiner = new StringJoiner(",", "{", "}");
        for (Method method : methods) {
            String methodName = method.getName();
            if ((methodName.startsWith("get") || methodName.startsWith("is")) && method.getParameterCount() == 0) {
                String keyName = methodName.substring(methodName.startsWith("get") ? 3 : 2).toLowerCase();
                Class returnType = method.getReturnType();
                Object v = method.invoke(value, new Object[]{});
                if (returnType.equals(int.class)) {
                    joiner.add("\"" + keyName + "\": " + v);
                } else if (returnType.equals(String.class)) {
                    joiner.add(String.format("\"%s\": \"%s\"", keyName, v));
                } else if (returnType.equals(boolean.class)) {
                    joiner.add("\"" + keyName + "\": " + v);
                }
            }
        }
        return joiner.toString();
    }
}
